package com.ildan.app.util;

import java.lang.reflect.Method;
import java.util.List;

import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.MapView.LayoutParams;
import com.ildan.app.toilet.BalloonOverlayView;
import com.ildan.app.toilet.R;

public abstract class BalloonItemizedOverlay<Item> extends ItemizedOverlay<OverlayItem>{
	private MapView mMapView;
	private BalloonOverlayView mBalloonView;
	private View clickRegion;
	private int viewOffset;
	public final MapController mMapController;
	
	public BalloonItemizedOverlay(Drawable defaultMarker, MapView mapView){
		super(defaultMarker);
		mMapView = mapView;
		viewOffset = 0;
		mMapController = mapView.getController();
	}
	
	/**
	 * Set the horizontal distance between the marker and the bottom of the information
	 * balloon. The default is 0 with well for center bounded markers. If your
	 * marker is center-bottom bounded, call this before adding overlay items to ensure
	 * the balloon hovers exactly above the marker.
	 * 
	 * @param pixels - The padding between the center point and the bottom of the
	 * information balloon.
	 */
	public void setBallonBottomOffset(int pixels){
		viewOffset = pixels;
	}
	
	/**
	 * Override the method to handle a "tap" on a balloon. By default, does nothing
	 * and return false.
	 * 
	 * @param index - The index of the item whose balloon is tapped.
	 * @return true if you handled the tap, otherwise false.
	 */
	protected boolean onBalloonTap(int index) {
		return false;
	}
	
	@Override
	public boolean onTap(int index) {
		
		Log.i("Result","index ===> "+index);
		boolean isRecycled;
		final int mIndex;
		GeoPoint point;
		
		mIndex = index;
		point = createItem(index).getPoint();
		
		if(mBalloonView == null){
			mBalloonView = new BalloonOverlayView(mMapView.getContext(), viewOffset);
			clickRegion = mBalloonView.findViewById(R.id.balloon_inner_layout);
			isRecycled = false;
		}else{
			isRecycled = true;
		}
		
		mBalloonView.setVisibility(View.GONE);
		
		List<Overlay> mapOverlay = mMapView.getOverlays();
		if(mapOverlay.size() > 1) hideOtherBalloons(mapOverlay);
		
		mBalloonView.setData(createItem(index));
		
		MapView.LayoutParams params = new MapView.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, point, MapView.LayoutParams.BOTTOM_CENTER);
		params.mode = MapView.LayoutParams.MODE_MAP;
		
		setBalloonTouchListener(mIndex);
		mBalloonView.setVisibility(View.VISIBLE);
		
		if(isRecycled) mBalloonView.setLayoutParams(params);
		else mMapView.addView(mBalloonView, params);
		
		mMapController.animateTo(point);
		
		return true;
	}
	
	/**
	 * Hides the balloon view for any other BalloonItemizedOverlay instances
	 * that might be present on the MapView.
	 * 
	 * @param overlays - list of overlays (including this) on the MapView.
	 */
	private void hideOtherBalloons(List<Overlay> overlays){
		for(Overlay overlay : overlays){
			if(overlay instanceof BalloonItemizedOverlay<?> && overlay != this){
				((BalloonItemizedOverlay<?>) overlay).hideBalloon();
			}
		}
	}
	
	/**
	 * Sets the visibility of this overlay's balloon view to GONE.
	 */
	private void hideBalloon(){
		if(mBalloonView != null) mBalloonView.setVisibility(View.GONE);
	}
	
	/**
	 * Sets the onTouchListener for the balloon being displayed, calling the overridden onBalloonTao if implemented.
	 *   
	 * @param index - The index of the item whose balloon is tapped.
	 */
	private void setBalloonTouchListener(final int index){
		try {
			@SuppressWarnings("unused")
			Method mh = this.getClass().getDeclaredMethod("onBalloonTap", int.class);
			
			clickRegion.setOnTouchListener(new OnTouchListener() {
				@Override
				public boolean onTouch(View v, MotionEvent event) {
					
					View mainView = ((View) v.getParent()).findViewById(R.id.balloon_main_layout);
					Drawable mDrawable = mainView.getBackground();
					
					if(event.getAction() == MotionEvent.ACTION_DOWN){
						int[] states = {android.R.attr.state_pressed};
						if(mDrawable.setState(states)){
							mDrawable.invalidateSelf();
						}
						return true;
					} else if (event.getAction() == MotionEvent.ACTION_UP){
						int newStates[] = {};
						if(mDrawable.setState(newStates)){
							mDrawable.invalidateSelf();
						}
						onBalloonTap(index);
						return true;
					} else{
	     				return false;
					}
				}
			});
			
		} catch (SecurityException e) {
			Log.e("BalloonItemizedOverlay","setBalloonTouchListener reflection SecurityException!!");
		} catch (NoSuchMethodException e) {
			return;
		}
	}

	
}
